package org.loginplugin.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.loginplugin.LoginPlugin;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.Properties;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class SqlSessionConfig {
    public static SqlSession session = init();

    public static SqlSession init() {
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        MybatisConfiguration configuration = new MybatisConfiguration();
        initConfiguration(configuration);
        configuration.addInterceptor(initInterceptor());

        //扫描DAO/Mapper所在包
        configuration.addMappers("org.loginplugin.mapper");
        //配置日志实现
        configuration.setLogImpl(Slf4jImpl.class);
        //构建mybatis-plus需要的globalconfig
        GlobalConfig globalConfig = new GlobalConfig();

        //此参数会自动生成实现baseMapper的基础方法映射
        globalConfig.setSqlInjector(new DefaultSqlInjector());
        //设置id生成器
        globalConfig.setIdentifierGenerator(new DefaultIdentifierGenerator());
        //设置超类mapper
        globalConfig.setSuperMapperClass(BaseMapper.class);

//        这里可以配置逻辑删除
        globalConfig.setDbConfig(initDBConfig());

        //给configuration注入GlobalConfig里面的配置
        GlobalConfigUtils.setGlobalConfig(configuration, globalConfig);
        //设置数据源
        Environment environment = new Environment("1", new JdbcTransactionFactory(), initDataSource());
        configuration.setEnvironment(environment);

//        设置xxxDAO.xml所在的目录
        try {
            registryMapperXml(configuration, "mapper");
        } catch (Exception e) {
            e.printStackTrace();
        }


        //构建sqlSessionFactory
        SqlSessionFactory sqlSessionFactory = builder.build(configuration);
        return sqlSessionFactory.openSession(true);
    }

    private static void initConfiguration(MybatisConfiguration configuration) {
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setUseGeneratedKeys(true);
    }

    //读取配置文件
//    private static Properties loadProperties() {
//        Properties properties = new Properties();
//        try (InputStream input = SqlSessionConfig.class.getClassLoader().getResourceAsStream("application.properties")) {
//            if (input == null) {
//                throw new RuntimeException("Unable to find application.properties");
//            }
//            properties.load(input);
//        } catch (IOException ex) {
//            throw new RuntimeException("Error loading application.properties", ex);
//        }
//        return properties;
//    }

    private static DataSource initDataSource() {
//        Properties properties = loadProperties();

        HikariDataSource dataSource = new HikariDataSource();
        String driver = LoginPlugin.FILE_CONFING.getString("mysql.driver", "com.mysql.cj.jdbc.Driver");
        String url = LoginPlugin.FILE_CONFING.getString("mysql.url", "127.0.0.1:3306/minecraft_plugin");
        String userName = LoginPlugin.FILE_CONFING.getString("mysql.username", "root");
        String password = LoginPlugin.FILE_CONFING.getString("mysql.password", "123456");

        dataSource.setJdbcUrl("jdbc:mysql://" + url + "?allowPublicKeyRetrieval=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&useUnicode=true");
        dataSource.setDriverClassName(driver);
        dataSource.setUsername(userName);
        dataSource.setPassword(password);
//        数据源设置，请按照当前DB参数设置
        dataSource.setIdleTimeout(60000);
        dataSource.setAutoCommit(true);
        dataSource.setMaximumPoolSize(5);
        dataSource.setMinimumIdle(1);
        dataSource.setMaxLifetime(60000 * 10);
        dataSource.setConnectionTestQuery("SELECT 1");
        return dataSource;
    }

    private static Interceptor initInterceptor() {
        //创建mybatis-plus插件对象
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //构建分页插件
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        paginationInnerInterceptor.setDbType(DbType.MYSQL);
        paginationInnerInterceptor.setOverflow(true);
        paginationInnerInterceptor.setMaxLimit(500L);
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        return interceptor;
    }

    private static GlobalConfig.DbConfig initDBConfig() {
        GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
//        逻辑删除字段
        dbConfig.setLogicDeleteField("enable");
        dbConfig.setLogicDeleteValue("0");
        dbConfig.setLogicNotDeleteValue("1");
        return dbConfig;
    }

    private static void registryMapperXml(MybatisConfiguration configuration, String classPath) throws IOException {

        //适用于jar包
//        URL url = SqlSessionConfig.class.getClassLoader().getResource(classPath);
//        if (url.getProtocol().equals("file")) {
//            File file = new File(url.getPath());
//            File[] files = file.listFiles();
//            for (File f : files) {
//                FileInputStream in = new FileInputStream(f);
//                XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(in, configuration, f.getPath(), configuration.getSqlFragments());
//                xmlMapperBuilder.parse();
//                in.close();
//            }
//        } else {
//            URLConnection urlConnection = url.openConnection();
//            if (urlConnection instanceof JarURLConnection) {
//                JarURLConnection jarURLConnection = (JarURLConnection) urlConnection;
//                JarFile jarFile = jarURLConnection.getJarFile();
//                Enumeration<JarEntry> entries = jarFile.entries();
//                while (entries.hasMoreElements()) {
//                    JarEntry jarEntry = entries.nextElement();
//                    if (jarEntry.getName().startsWith(classPath + "/") && jarEntry.getName().endsWith(".xml")) {
//                        InputStream in = jarFile.getInputStream(jarEntry);
//                        XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(in, configuration, jarEntry.getName(), configuration.getSqlFragments());
//                        xmlMapperBuilder.parse();
//                        in.close();
//                    }
//                }
//            }
//        }

        //适用于普通应用程序
//        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
//        Enumeration<URL> mapper = contextClassLoader.getResources("mapper");
        Enumeration<URL> mapper = SqlSessionConfig.class.getClassLoader().getResources(classPath);
        while (mapper.hasMoreElements()) {
            URL url = mapper.nextElement();
            if (url.getProtocol().equals("file")) {
                File file = new File(url.getPath());
                File[] files = file.listFiles();
                for (File f : files) {
                    FileInputStream in = new FileInputStream(f);
                    XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(in, configuration, f.getPath(), configuration.getSqlFragments());
                    xmlMapperBuilder.parse();
                    in.close();
                }
            } else {
                JarURLConnection urlConnection = (JarURLConnection) url.openConnection();
                JarFile jarFile = urlConnection.getJarFile();
                Enumeration<JarEntry> entries = jarFile.entries();
                while (entries.hasMoreElements()) {
                    JarEntry jarEntry = entries.nextElement();
                    if (jarEntry.getName().endsWith(".xml")) {
                        InputStream in = jarFile.getInputStream(jarEntry);
                        XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(in, configuration, jarEntry.getName(), configuration.getSqlFragments());
                        xmlMapperBuilder.parse();
                        in.close();
                    }
                }
            }
        }
    }
}